﻿using Abp.Authorization;
using Abp.Runtime.Session;
using Abp.Specifications;
using Abp.UI;
using Paas.App.Interface.Common;
using Paas.App.Interface.Common.Dtos;
using Paas.App.Interface.Common.Messages;
using Paas.Core;
using Paas.Core.Common.Entities;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Basefr.App;
using Basefr.Core.Extensions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace Paas.App.Common
{
    [Route("Notice")]
    [AbpAuthorize()]
    public class NoticeAppService : AppService, INoticeAppService
    {
        private readonly IMainRepository<Notice> _noticeRepo;

        public NoticeAppService(IMainRepository<Notice> noticeRepo)
        {
            _noticeRepo = noticeRepo;
        }

        [HttpPost(nameof(SearchAllNotice))]
        public virtual SearchAllNoticeOutput SearchAllNotice(SearchAllNoticeInput input)
        {
            Expression<Func<Notice, bool>> predicate = p => true;

            if (!string.IsNullOrWhiteSpace(input.Keyword))
            {
                var keyword = input.Keyword.Trim();
                predicate = predicate.And(p => p.Title.Contains(keyword) || p.Content.Contains(keyword) || p.To.Name.Contains(keyword));
            }

            var result = _noticeRepo.GetAll()
                .Include(p => p.To)
                .Where(predicate)
                .OrderByDescending(p => p.Id)
                .GetPage(input.SkipCount, input.MaxResultCount, out var total, out var isOverPaged)
                .ToList();

            return new SearchAllNoticeOutput { Items = ObjectMapper.Map<List<NoticeDto>>(result), TotalCount = total, IsOverPaged = isOverPaged };
        }

        [HttpPost(nameof(SearchNotice))]
        public virtual SearchNoticeOutput SearchNotice(SearchNoticeInput input)
        {
            Expression<Func<Notice, bool>> predicate = p => p.ToId == AbpSession.GetUserId();

            if (!string.IsNullOrWhiteSpace(input.Keyword))
            {
                var keyword = input.Keyword.Trim();
                predicate = predicate.And(p => p.Title.Contains(keyword) || p.Content.Contains(keyword));
            }

            var result = _noticeRepo.GetAll().Where(predicate).OrderByDescending(p => p.Id).GetPage(input.SkipCount, input.MaxResultCount, out var total, out var isOverPaged).ToList();

            return new SearchNoticeOutput { Items = ObjectMapper.Map<List<NoticeDto>>(result), TotalCount = total, IsOverPaged = isOverPaged };
        }

        [HttpPost(nameof(SaveNotice))]
        public virtual SaveNoticeOutput SaveNotice(SaveNoticeInput input)
        {
            input.Item.Title = input.Item.Title.Trim();
            input.Item.Content = input.Item.Content.Trim();

            if (_noticeRepo.GetAll().Any(p => p.Id != input.Item.Id && p.Title == input.Item.Title))
            {
                throw new UserFriendlyException("通知消息标题不能重复，已存在相同的通知标题");
            }

            if (input.Item.Id <= 0)
            {
                var entity = ObjectMapper.Map<Notice>(input.Item);

                _noticeRepo.Insert(entity);

                return new SaveNoticeOutput();
            }

            var exist = _noticeRepo.Get(input.Item.Id);

            exist.Title = input.Item.Title;
            exist.Content = input.Item.Content;

            return new SaveNoticeOutput();
        }

        [HttpPost(nameof(ReadNotice))]
        public virtual ReadNoticeOutput ReadNotice(ReadNoticeInput input)
        {
            var notice = _noticeRepo.Get(input.NoticeId);

            if (notice.ToId != AbpSession.GetUserId())
            {
                throw new UserFriendlyException("通知消息无效");
            }

            notice.IsRead = true;

            return new ReadNoticeOutput();
        }

        [HttpPost(nameof(DeleteNotice))]
        public virtual DeleteNoticeOutput DeleteNotice(DeleteNoticeInput input)
        {
            var item = _noticeRepo.Get(input.Id);

            _noticeRepo.Delete(item);

            return new DeleteNoticeOutput();
        }
    }
}

